﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AAA.Meta.Chart.Data
{
    public class PriceVolumeData
    {
        private List<float> _lstPrice;
        private List<float> _lstVolume;
        private List<float> _lstTickVolume;

        private DateTime _dtStartTime;
        private DateTime _dtEndTime;

        private float _fVolumePOC;
        private float _fTickVolumePOC;
        private float _fTimeVolumePOC;

        private float _fVolumePOCVol;
        private float _fTickVolumePOCVol;
        private float _fTimeVolumePOCVol;

        private float _fMaxPrice;
        private float _fMinPrice;

        private bool _isCalculated;


        public PriceVolumeData()
        {
            _lstPrice = new List<float>();
            _lstVolume = new List<float>();
            _lstTickVolume = new List<float>();
            _isCalculated = false;
            _dtStartTime = DateTime.MaxValue;
            _dtEndTime = DateTime.MinValue;
            _fMaxPrice = -float.MaxValue;
            _fMinPrice = float.MaxValue;
        }

        public void AddData(float fPrice, float fVolume)
        {
            AddData(fPrice, fVolume, 1);
        }

        public void AddData(float fPrice, float fVolume, float fTickVolume)
        {
            AddData(fPrice, fVolume, fTickVolume, DateTime.MinValue);
        }

        public void AddData(float fPrice, float fVolume, float fTickVolume, DateTime dtExTime)
        {
            int iIndex = _lstPrice.IndexOf(fPrice);
            _isCalculated = false;

            if (fPrice > _fMaxPrice)
                _fMaxPrice = fPrice;

            if (fPrice < _fMinPrice)
                _fMinPrice = fPrice;

            if ((dtExTime > _dtEndTime) && (dtExTime != DateTime.MinValue))
                _dtEndTime = dtExTime;

            if ((dtExTime < _dtStartTime) && (dtExTime != DateTime.MinValue))
                _dtStartTime = dtExTime;

            if (iIndex < 0)
            {
                _lstPrice.Add(fPrice);
                _lstVolume.Add(fVolume);
                _lstTickVolume.Add(fTickVolume);
            }
            else
            {
                _lstVolume[iIndex] += fVolume;
                _lstTickVolume[iIndex] += fTickVolume;
            }            
        }

        private void CalculatePOC()
        {
            float fMaxVolume = 0;
            float fMaxTickVolume = 0;
            float fMaxTimeVolume = 0;

            _fVolumePOC = 0;
            _fTickVolumePOC = 0;
            _fTimeVolumePOC = 0;

            for (int i = 0; i < _lstPrice.Count; i++)
            {
                if (_lstVolume[i] > fMaxVolume)
                {
                    fMaxVolume = _lstVolume[i];
                    _fVolumePOC = _lstPrice[i];
                    _fTimeVolumePOCVol = fMaxVolume;
                }

                if (_lstTickVolume[i] > fMaxTickVolume)
                {
                    fMaxTickVolume = _lstVolume[i];
                    _fTickVolumePOC = _lstPrice[i];
                    _fTimeVolumePOCVol = fMaxTickVolume;
                }
            }
            _isCalculated = true;
        }

        public float POCPrice(VolumeTypeEnum eVolumeType)
        {

            if (!_isCalculated)
                CalculatePOC();

            switch (eVolumeType)
            {
                case VolumeTypeEnum.Volume:                    
                    return _fVolumePOC;

                case VolumeTypeEnum.TickVolume:
                    return _fTickVolumePOC;

                case VolumeTypeEnum.TimeVolume:
                    return _fTimeVolumePOC;

            }

            return float.NaN;
        }

        public float POCVolume(VolumeTypeEnum eVolumeType)
        {
            if (!_isCalculated)
                CalculatePOC();

            switch (eVolumeType)
            {
                case VolumeTypeEnum.Volume:                    
                    return _fVolumePOCVol;

                case VolumeTypeEnum.TickVolume:
                    return _fTickVolumePOCVol;

                case VolumeTypeEnum.TimeVolume:
                    return _fTimeVolumePOCVol;

            }

            return float.NaN;
        }

        public DateTime StartTime
        {
            get { return _dtStartTime; }
            set { _dtStartTime = value; }
        }

        public DateTime EndTime
        {
            get { return _dtEndTime; }
            set { _dtEndTime = value; }
        }

        public List<float> Price
        {
            get { return _lstPrice; }
        }

        public List<float> Volume
        {
            get { return _lstVolume; }
        }

        public List<float> TickVolume
        {
            get { return _lstTickVolume; }
        }
    }
}
